package com.hh.base.log

import java.io.File
import java.util.concurrent.atomic.AtomicReference

/**
 * Create By hHui on 2025/4/3 16:14
 *
 * @description 日志工具
 */
class Logger {
    enum class Type {
        Logcat, File, Net
    }

    private val printer = ArrayList<ILog>()

    private var level: Int = VERBOSE

    constructor(types: Array<Type>, level: Int, file: File?, host: String?, port: Int?) {
        printer.clear()
        types.forEach {
            when (it) {
                Type.Logcat -> printer.add(CatLog())
                Type.File -> {
                    if (file != null) {
                        printer.add(FileLog(file))
                    }
                }

                Type.Net -> {
                    if (host != null && port != null) {
                        printer.add(NetLog(host, port))
                    }
                }
            }
        }
        this.level = level
    }

    private constructor() {
        printer.add(CatLog())
        this.level = VERBOSE
    }

    companion object {
        const val VERBOSE: Int = 0
        const val DEBUG: Int = 1
        const val INFO: Int = 2
        const val WARN: Int = 3
        const val ERROR: Int = 4
        private var logger: AtomicReference<Logger> = AtomicReference()
        private lateinit var logTypes: Array<Type>

        /**
         * 初始化
         */
        @JvmStatic
        fun init(types: Array<Type>, level: Int, file: File? = null, host: String? = null, port: Int? = null) {
            if (this.logger.get() == null) {
                logTypes = types
                if (types.contains(Type.Net)) {
                    if (host == null || port == null) {
                        throw Exception("使用远程日志必须传入服务器地址和端口")
                    }
                }
                val logger = Logger(types, level, file, host, port)
                this.logger = AtomicReference(logger)
            }
        }

        @JvmStatic
        fun dft(): Logger {
            return if (logger.get() == null) {
                val logger = Logger()
                this.logger = AtomicReference(logger)
                logger
            } else {
                logger.get()
            }
        }

        fun of(types: Array<Type>, level: Int, file: File? = null, host: String? = null, port: Int? = null): Logger {
            return Logger(types, level, file, host, port)
        }
    }

    @JvmOverloads
    fun v(tag: String, msg: String?, t: Throwable? = null) {
        if (level <= VERBOSE) {
            printer.forEach {
                it.v(tag, msg, t)
            }
        }
    }

    @JvmOverloads
    fun d(tag: String, msg: String?, t: Throwable? = null) {
        if (level <= DEBUG) {
            printer.forEach {
                it.d(tag, msg, t)
            }
        }
    }

    @JvmOverloads
    fun i(tag: String, msg: String?, t: Throwable? = null) {
        if (level <= INFO) {
            printer.forEach {
                it.i(tag, msg, t)
            }
        }
    }

    @JvmOverloads
    fun w(tag: String, msg: String?, t: Throwable? = null) {
        if (level <= WARN) {
            printer.forEach {
                it.w(tag, msg, t)
            }
        }
    }

    @JvmOverloads
    fun e(tag: String, msg: String?, t: Throwable? = null) {
        if (level <= ERROR) {
            printer.forEach {
                it.e(tag, msg, t)
            }
        }
    }

    fun dispose() {
        printer.forEach {
            it.dispose()
        }
    }
}